﻿using AJWPFAdmin.Views;
using AJWPFAdmin.Core;
using AJWPFAdmin.Core.Logger;
//using AJWPFAdmin.Modules.Header;
using AJWPFAdmin.Modules.Main;
using AJWPFAdmin.Modules.SideMenu;
using AJWPFAdmin.Services;
using AJWPFAdmin.Services.EF;
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.Configuration;
using Prism.Ioc;
using Prism.Modularity;
using Prism.Regions;
using System;
using System.Diagnostics;
using System.Threading.Tasks;
using System.Windows;
using LiveChartsCore;
using LiveChartsCore.SkiaSharpView;
using SkiaSharp;
using System.Globalization;
using System.Threading;
using System.Collections;
using AJWPFAdmin.Services.Jobs;
using System.Collections.Generic;
using AJWPFAdmin.Core.HardwareSDKS;
using AJWPFAdmin.Core.Utils;
using System.IO;
using Prism.Events;
using AJWPFAdmin.Core.GlobalEvents;
using System.Text;
using AJWPFAdmin.Modules.Common;
using AJWPFAdmin.Modules.Common.Views;
using AJWPFAdmin.Core.HardwareSDKS.FFmpeg;
using FFmpeg.AutoGen;
using Yitter.IdGenerator;
using System.Reflection;
using AJWPFAdmin.Services.AppointAPI;
using DryIoc;
using Microsoft.Extensions.DependencyInjection;
using Prism.DryIoc;
using DryIoc.Microsoft.DependencyInjection;
using EntranceGuardClient.Services;

namespace AJWPFAdmin
{
    /// <summary>
    /// Interaction logic for App.xaml
    /// </summary>
    public partial class App
    {
        protected override Window CreateShell()
        {
            return Container.Resolve<LoginWindow>();
        }

        protected override IContainerExtension CreateContainerExtension()
        {
            var services = new ServiceCollection();
            ConfigureServices(services);

            var container = new DryIoc.Container(CreateContainerRules());
            container.WithDependencyInjectionAdapter(services);

            return new DryIocContainerExtension(container);
        }

        protected override Rules CreateContainerRules()
        {
            return Rules.Default.WithConcreteTypeDynamicRegistrations(reuse: Reuse.Transient)
                .With(Made.Of(FactoryMethod.ConstructorWithResolvableArguments))
                .WithFuncAndLazyWithoutRegistration()
                .WithTrackingDisposableTransients()
                .WithFactorySelector(Rules.SelectLastRegisteredFactory());
        }

        private void ConfigureServices(IServiceCollection services)
        {
            services.AddMemoryCache();
            services.AddSingleton(typeof(ICacheConfig<>), typeof(CacheConfig<>));
            services.AddSingleton(typeof(IBaseNonTableCache<>), typeof(BaseNonTableCache<>));
            services.AddSingleton<AJConfigService>();
            services.AddSingleton<DbService>(provider =>
            {
                var cfgSvc = provider.GetService<AJConfigService>();

                var builder = new DbContextOptionsBuilder<DbService>();
                var version = new MySqlServerVersion(ServerVersion.Parse("8.0.34-mysql"));
                builder.UseMySql(cfgSvc.Config.GetConnectionString("MYSQL"), version,
                    bd =>
                    {
                        bd.EnableRetryOnFailure(3);
                    }).EnableDetailedErrors();
                //.LogTo(log => Debug.WriteLine(log),
                // new[] {
                //     DbLoggerCategory.Database.Command.Name,
                //     DbLoggerCategory.Update.Name,
                //     DbLoggerCategory.Query.Name
                // });
                return new DbService(builder.Options);
            });
            AppointAPISvc.Init(services);

        }

        protected override void RegisterTypes(IContainerRegistry containerRegistry)
        {
            containerRegistry.RegisterSingleton<AJConfigService>();
            containerRegistry.RegisterSingleton<DbService>(provider =>
            {
                var cfgSvc = provider.Resolve<AJConfigService>();

                var builder = new DbContextOptionsBuilder<DbService>();
                var version = new MySqlServerVersion(ServerVersion.Parse("8.0.34-mysql"));
                builder.UseMySql(cfgSvc.Config.GetConnectionString("MYSQL"), version,
                    bd =>
                    {
                        bd.EnableRetryOnFailure(3);
                    }).EnableDetailedErrors();
                //.LogTo(log => Debug.WriteLine(log),
                // new[] {
                //     DbLoggerCategory.Database.Command.Name,
                //     DbLoggerCategory.Update.Name,
                //     DbLoggerCategory.Query.Name
                // });
                return new DbService(builder.Options);
            });

            containerRegistry.RegisterSingleton<AJLog4NetLogger>();
            containerRegistry.RegisterSingleton<ExceptionTool>();
            containerRegistry.RegisterSingleton<AJDatabaseckupService>();
            containerRegistry.RegisterSingleton<SystemUserService>();
            containerRegistry.RegisterSingleton<QuarztTaskService>();
            containerRegistry.RegisterSingleton<AJMQTTService>();

            containerRegistry.RegisterSingleton<AppointAPISvc>(provider =>
            {
                return new AppointAPISvc(ApplicationType.岗亭端, provider);
            });

            containerRegistry.RegisterSingleton<MainApplicationBridgeService>((provider) =>
            {
                var mbs = new MainApplicationBridgeService();
                mbs.RegisterFolderBrowser(new FolderBrowserBridge());
                return mbs;
            });


        }

        protected override void ConfigureModuleCatalog(IModuleCatalog moduleCatalog)
        {
            moduleCatalog.AddModule<MainModule>();
            moduleCatalog.AddModule<SideMenuModule>();
            moduleCatalog.AddModule<CommonModule>();
        }

        protected async override void OnStartup(StartupEventArgs e)
        {
            var currentProcess = Process.GetCurrentProcess();

            if (Process.GetProcessesByName(currentProcess.ProcessName)?.Length > 1)
            {
                MessageBox.Show("程序已经运行", "提示", MessageBoxButton.OK);
                currentProcess.Kill();
                return;
            }
            base.OnStartup(e);
            YitIdHelper.SetIdGenerator(new IdGeneratorOptions(1)
            {
                SeqBitLength = 8
            });

            // 注册FFmpeg
            FFmpegUtil.Init();
            //  注册 GB2312
            Encoding.RegisterProvider(CodePagesEncodingProvider.Instance);
            var task = Container.Resolve<QuarztTaskService>();
            await task.StartAsync(Container, new List<IAJJob>
            {
                new DatabaseBackupJob(),
                new CarExpiredCheckJob(),
                new AppointAPIDataVerificationUploadJob(),
                new AppointAPIUploadFailedRecordJob(),
            });
            this.DispatcherUnhandledException += App_DispatcherUnhandledException;
            TaskScheduler.UnobservedTaskException += TaskScheduler_UnobservedTaskException;
            AppDomain.CurrentDomain.UnhandledException += CurrentDomain_UnhandledException;

            // 创建桌面快捷方式
            CommonUtil.CreateShortcut("门禁系统岗亭端", "门禁系统岗亭端", Application.ResourceAssembly);
            //LiveCharts.Configure(cfg =>
            //{

            //});
        }

        protected async override void OnExit(ExitEventArgs e)
        {
            var task = Container.Resolve<QuarztTaskService>();
            await task.StopAsync();

            //var mqttSvc = Container.Resolve<AJMQTTService>();
            //await mqttSvc.CloseAsync(true);

            var eventAggregator = Container.Resolve<IEventAggregator>();

            eventAggregator.GetEvent<ApplicationExitEvent>().Publish();

            var appointSvc = Container.Resolve<AppointAPISvc>();
            appointSvc.API.Dispose();

            var cfgSvc = Container.Resolve<AJConfigService>();
            cfgSvc.Dispose();

            base.OnExit(e);
        }

        private void CurrentDomain_UnhandledException(object sender, UnhandledExceptionEventArgs e)
        {
            try
            {
                if (e.IsTerminating)
                {
                    var ext = Container.Resolve<ExceptionTool>();
                    ext.LogException((e.ExceptionObject as Exception));

                }
            }
            catch
            {

            }

        }

        private void TaskScheduler_UnobservedTaskException(object sender, UnobservedTaskExceptionEventArgs e)
        {
            try
            {
                e.SetObserved();
                var ext = Container.Resolve<ExceptionTool>();
                ext.LogException(e.Exception);
            }
            catch
            {
            }

        }

        private async void App_DispatcherUnhandledException(object sender, System.Windows.Threading.DispatcherUnhandledExceptionEventArgs e)
        {
            try
            {
                e.Handled = true;
                var ext = Container.Resolve<ExceptionTool>();
                ext.LogException(e.Exception);

            }
            catch
            {

            }


        }
    }
}
